import java.math.BigInteger;


public class Utils {
	public final static int size = 256;
	
	public static int[] tau(byte[] x) {
		int[] tau = new int[size];
		
		for (int i = 0; i < x.length; i++) {
			tau[x[i] & 255]++;
		}
		
		return tau;
	}
	
	private static BigInteger countTaus(int n, int m) {
		return CNK.c(n + m - 1, m - 1);
	}
	
	private static BigInteger tauIndexImpl(int[] tau, int offset, int n) {
		int m = tau.length - offset;
		if (offset == tau.length) {
			return BigInteger.ZERO;
		}
 		BigInteger rv = BigInteger.ZERO;
		for (int t = 0; t < tau[offset]; ++t) {
			rv = rv.add(countTaus(n - t, m - 1));
		}
		return rv.add(tauIndexImpl(tau, offset + 1, n - tau[offset]));
	}
	
	public static String tauIndex(int[] tau) {
		int n = 0;
		for (int i : tau) n += i;
		int m = tau.length;
		BigInteger index = tauIndexImpl(tau, 0, n);
		BigInteger maximum = countTaus(n, m).subtract(BigInteger.ONE);
		StringBuilder rv = new StringBuilder();
		for (int t = index.bitLength(); t < maximum.bitLength(); ++t) {
			rv.append("0");
		}
		if (index.signum() != 0 || rv.length() < maximum.bitLength()) {
			rv.append(index.toString(2));
		}
		return rv.toString();
	}
}
